<template>
  <div ref="chartContainer" class="d3-chart 12121"></div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, computed, watch } from "vue";
import * as d3 from "d3";
import { useAppStore } from "@/store";
import { DeviceEnum } from "@/enums/index.js";

const props = defineProps({
  modelValue: Object,
  treeList: Array,
  currentUserId: String,
  title: String
});

const emit = defineEmits([
  'node-click'
]);

const appStore = useAppStore();
const chartContainer = ref(null);
let svg;
let zoom;
let currentTransform = null;

// 渲染家谱树
function renderTree(data) {
  if (!chartContainer.value) return;
  
  // 清除之前的内容
  d3.select(chartContainer.value).selectAll("*").remove();

  // 将单一树转换为树列表
  const treeList = Array.isArray(data) ? data : [data];
  
  // 如果列表为空或第一个元素没有firstName，则返回
  if (treeList.length === 0 || !treeList[0].firstName) return;

  const width = 1200;
  const height = 800;
  
  // 节点尺寸和间距
  const nodeWidth = 130;
  const nodeHeight = 90;
  const baseSpouseSpacing = 220; // 基础配偶间距
  const levelSpacing = 220; // 层级间距
  const baseSiblingSpacing = 170; // 基础兄弟节点间距

  // 创建SVG容器
  svg = d3.select(chartContainer.value)
    .append("svg")
    .attr("width", "100%")
    .attr("height", "100%")
    .attr("viewBox", `0 0 ${width} ${height}`)
    .style("background-color", "#f8f9fa");

  const g = svg.append("g");
  
  // 添加标题
  svg.append("text")
    .attr("x", width / 2)
    .attr("y", 40)
    .attr("text-anchor", "middle")
    .attr("font-size", "24px")
    .attr("font-weight", "bold")
    .attr("fill", "#2c3e50")
    .text(props.title || "家族谱系图");

  // 添加缩放功能
  zoom = d3.zoom()
    .scaleExtent([0.1, 2])
    .on("zoom", (event) => {
      g.attr("transform", event.transform);
      currentTransform = event.transform;
    });

  svg.call(zoom);

  // 初始缩放
  const initialScale = 0.7;
  const initialTransform = d3.zoomIdentity.scale(initialScale).translate(width * 0.2, height * 0.2);
  
  if (currentTransform) {
    svg.call(zoom.transform, currentTransform);
  } else {
    svg.call(zoom.transform, initialTransform);
    currentTransform = initialTransform;
  }

  // 为每棵树创建布局
  treeList.forEach((treeData, treeIndex) => {
    // 预先计算每个节点的配偶数量，用于后续间距调整
    function calculateSpouses(node) {
      node.spouseCount = node.spouseList ? node.spouseList.length : 0;
      if (node.children && node.children.length > 0) {
        node.children.forEach(calculateSpouses);
      }
      return node;
    }
    
    // 计算每个节点的子节点数量，用于调整兄弟节点间距
    function calculateChildrenCount(node) {
      if (!node.children || node.children.length === 0) {
        node.totalChildrenCount = 0;
        return 0;
      }
      
      let totalCount = 0;
      node.children.forEach(child => {
        totalCount += calculateChildrenCount(child) + 1;
      });
      
      node.totalChildrenCount = totalCount;
      return totalCount;
    }
    
    // 应用计算
    calculateSpouses(treeData);
    calculateChildrenCount(treeData);
    
    // 创建树布局
    const treeLayout = d3.tree()
      .size([width * 0.8, height - 120])
      .nodeSize([baseSiblingSpacing, levelSpacing])
      .separation((a, b) => {
        // 动态计算节点间距
        const aSpouses = a.data.spouseCount || 0;
        const bSpouses = b.data.spouseCount || 0;
        
        // 基础间距系数
        let baseSeparation = a.parent === b.parent ? 1.5 : 2;
        
        // 根据配偶数量增加间距
        let spouseAdjustment = (aSpouses + bSpouses) * 0.8;
        
        // 根据子节点数量增加间距
        const aChildren = a.data.totalChildrenCount || 0;
        const bChildren = b.data.totalChildrenCount || 0;
        let childrenAdjustment = Math.max(aChildren, bChildren) * 0.3;
        
        return baseSeparation + spouseAdjustment + childrenAdjustment;
      });

    const root = d3.hierarchy(treeData);
    treeLayout(root);

    // 创建每棵树的容器
    const treeG = g.append("g")
      .attr("class", `tree-${treeIndex}`)
      .attr("transform", `translate(${treeIndex * (width * 0.8 + 100)}, 0)`);
    
    // 计算树的整体宽度，用于居中显示
    const xOffset = 100;
    const yOffset = 100;

    // 添加连接线阴影滤镜
    svg.append("defs")
      .append("filter")
      .attr("id", "drop-shadow")
      .append("feDropShadow")
      .attr("dx", 0)
      .attr("dy", 1)
      .attr("stdDeviation", 1)
      .attr("flood-opacity", 0.2);

    // 绘制连接线
    treeG.selectAll(".link")
      .data(root.links())
      .enter()
      .append("path")
      .attr("class", "link")
      .attr("d", d => {
        const sourceX = d.source.x + xOffset;
        const sourceY = d.source.y + yOffset;
        const targetX = d.target.x + xOffset;
        const targetY = d.target.y + yOffset;
        
        return `M${sourceX},${sourceY} L${sourceX},${(sourceY + targetY) / 2} L${targetX},${(sourceY + targetY) / 2} L${targetX},${targetY}`;
      })
      .attr("fill", "none")
      .attr("stroke", "#a0a0a0")
      .attr("stroke-width", 1.5)
      .attr("stroke-linecap", "round")
      .attr("stroke-linejoin", "round");

    // 预先创建夫妻连接线
    root.descendants().forEach(d => {
      if (d.data.spouseList && d.data.spouseList.length > 0) {
        const spouses = d.data.spouseList;
        const nodeX = d.x + xOffset;
        const nodeY = d.y + yOffset;
        
        // 动态计算配偶间距
        const spouseCount = spouses.length;
        // 如果配偶数量多，适当减小间距
        const adjustedSpacing = spouseCount > 1 
          ? baseSpouseSpacing * (1 - 0.1 * (spouseCount - 1)) 
          : baseSpouseSpacing;
        
        spouses.forEach((spouse, i) => {
          treeG.append("line")
            .attr("class", "spouse-link")
            .attr("x1", nodeX)
            .attr("y1", nodeY)
            .attr("x2", nodeX + (i + 1) * adjustedSpacing)
            .attr("y2", nodeY)
            .attr("stroke", "#a0a0a0")
            .attr("stroke-width", 1.5)
            .attr("stroke-dasharray", "5,3");
        });
      }
    });

    // 添加节点
    const nodes = treeG.selectAll(".node")
      .data(root.descendants())
      .enter()
      .append("g")
      .attr("class", "node")
      .attr("transform", d => `translate(${d.x + xOffset},${d.y + yOffset})`)
      .on("click", (event, d) => {
        event.stopPropagation();
        emit('node-click', d.data);
      });

    // 节点矩形
    nodes.append("rect")
      .attr("width", nodeWidth)
      .attr("height", nodeHeight)
      .attr("x", -nodeWidth/2)
      .attr("y", -nodeHeight/2)
      .attr("rx", 10)
      .attr("ry", 10)
      .attr("data-user-id", d => d.data.id)
      .attr("fill", d => {
        if (d.data.id === props.currentUserId) {
          return "#fff7e6"; // 当前用户
        }
        if (d.data.alive === 0) {
          return "#f0f0f0"; // 已故成员
        }
        return d.data.gender === 1 ? "#e8f4ff" : "#fff0f7";
      })
      .attr("stroke", d => {
        if (d.data.id === props.currentUserId) {
          return "#ffc107"; // 当前用户边框颜色
        }
        return d.data.gender === 1 ? "#4a89dc" : "#ec6b9e";
      })
      .attr("stroke-width", d => d.data.id === props.currentUserId ? 3 : 1.5)
      .style("filter", "url(#drop-shadow)")
      .style("cursor", "pointer")
      .style("transition", "all 0.2s ease");

    // 添加性别图标
    nodes.append("circle")
      .attr("cx", -nodeWidth/2 + 15)
      .attr("cy", -nodeHeight/2 + 15)
      .attr("r", 10)
      .attr("fill", d => d.data.gender === 1 ? "#4a89dc" : "#ec6b9e");

    nodes.append("text")
      .attr("x", -nodeWidth/2 + 15)
      .attr("y", -nodeHeight/2 + 15)
      .attr("text-anchor", "middle")
      .attr("dominant-baseline", "central")
      .attr("fill", "#ffffff")
      .attr("font-size", "12px")
      .attr("font-weight", "bold")
      .text(d => d.data.gender === 1 ? "男" : "女");

    // 节点姓名文字
    nodes.append("text")
      .text(d => `${d.data.firstName}${d.data.lastName}`)
      .attr("text-anchor", "middle")
      .attr("x", 0)
      .attr("y", -10)
      .attr("dy", "0.3em")
      .style("font-size", "16px")
      .style("font-weight", "bold")
      .style("fill", "#333")
      .style("pointer-events", "none");

    // 添加生命状态标记
    nodes.append("text")
      .text(d => d.data.alive === 0 ? "已故" : "")
      .attr("text-anchor", "middle")
      .attr("x", 0)
      .attr("y", 15)
      .attr("dy", "0.3em")
      .style("font-size", "12px")
      .style("fill", "#888")
      .style("pointer-events", "none");

    // 绘制配偶节点
    nodes.each(function(d) {
      const node = d3.select(this);
      const spouses = d.data.spouseList || [];
      
      // 动态计算配偶间距
      const spouseCount = spouses.length;
      // 如果配偶数量多，适当减小间距
      const adjustedSpacing = spouseCount > 1 
        ? baseSpouseSpacing * (1 - 0.1 * (spouseCount - 1)) 
        : baseSpouseSpacing;

      spouses.forEach((spouse, i) => {
        const spouseGroup = node.append("g")
          .attr("class", "spouse-node")
          .attr("transform", `translate(${(i + 1) * adjustedSpacing},0)`)
          .on("click", (event) => {
            event.stopPropagation();
            emit('node-click', spouse);
          });

        spouseGroup.append("rect")
          .attr("width", nodeWidth)
          .attr("height", nodeHeight)
          .attr("x", -nodeWidth/2)
          .attr("y", -nodeHeight/2)
          .attr("rx", 10)
          .attr("ry", 10)
          .attr("fill", spouse => {
            if (spouse.alive === 0) {
              return "#f0f0f0"; // 已故配偶
            }
            return spouse.gender === 1 ? "#e8f4ff" : "#fff0f7";
          })
          .attr("stroke", spouse => spouse.gender === 1 ? "#4a89dc" : "#ec6b9e")
          .attr("stroke-width", 1.5)
          .style("filter", "url(#drop-shadow)")
          .style("cursor", "pointer")
          .style("transition", "all 0.2s ease");

        // 添加性别图标
        spouseGroup.append("circle")
          .attr("cx", -nodeWidth/2 + 15)
          .attr("cy", -nodeHeight/2 + 15)
          .attr("r", 10)
          .attr("fill", spouse => spouse.gender === 1 ? "#4a89dc" : "#ec6b9e");

        spouseGroup.append("text")
          .attr("x", -nodeWidth/2 + 15)
          .attr("y", -nodeHeight/2 + 15)
          .attr("text-anchor", "middle")
          .attr("dominant-baseline", "central")
          .attr("fill", "#ffffff")
          .attr("font-size", "12px")
          .attr("font-weight", "bold")
          .text(spouse => spouse.gender === 1 ? "男" : "女");

        // 配偶姓名
        spouseGroup.append("text")
          .text(`${spouse.firstName}${spouse.lastName}`)
          .attr("text-anchor", "middle")
          .attr("x", 0)
          .attr("y", -10)
          .attr("dy", "0.3em")
          .style("font-size", "16px")
          .style("font-weight", "bold")
          .style("fill", "#333")
          .style("pointer-events", "none");

        // 添加生命状态标记
        spouseGroup.append("text")
          .text(spouse => spouse.alive === 0 ? "已故" : "")
          .attr("text-anchor", "middle")
          .attr("x", 0)
          .attr("y", 15)
          .attr("dy", "0.3em")
          .style("font-size", "12px")
          .style("fill", "#888")
          .style("pointer-events", "none");
      });
    });
  });
}

// 监听数据变化
watch(() => [props.modelValue, props.treeList], ([newModelValue, newTreeList]) => {
  if (newTreeList && newTreeList.length > 0) {
    renderTree(newTreeList);
  } else if (newModelValue) {
    renderTree(newModelValue);
  }
}, { deep: true });

// 组件挂载时初始化
onMounted(() => {
  if (props.treeList && props.treeList.length > 0) {
    renderTree(props.treeList);
  } else if (props.modelValue) {
    renderTree(props.modelValue);
  }
});

// 组件卸载前清理
onBeforeUnmount(() => {
  if (svg) {
    svg.selectAll("*").remove();
  }
});

// 导出方法
defineExpose({
  renderTree
});
</script>

<style scoped>
.d3-chart {
  width: 100%;
  height: 100%;
  min-height: 600px;
  position: relative;
  background-color: #f8f9fa;
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  padding: 20px;
  overflow: hidden;
}

.node:hover rect, .spouse-node:hover rect {
  filter: brightness(0.95);
  transform: scale(1.03);
}

/* 自定义滚动条 */
.d3-chart::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

.d3-chart::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 4px;
}

.d3-chart::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 4px;
}

.d3-chart::-webkit-scrollbar-thumb:hover {
  background: #a8a8a8;
}
</style> 